-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[libc++] Simplify the implementation of aligned_storage #162459
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-libcxx Author: Nikolas Klauser (philnik777) ChangesFull diff: https://github.com/llvm/llvm-project/pull/162459.diff 2 Files Affected:
diff --git a/libcxx/include/__config b/libcxx/include/__config
index b4c081dcdff1b..a77d40636838a 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -339,7 +339,7 @@ _LIBCPP_HARDENING_MODE_DEBUG
# ifndef _LIBCPP_CXX03_LANG
-# define _LIBCPP_ALIGNOF(_Tp) alignof(_Tp)
+# define _LIBCPP_ALIGNOF(...) alignof(__VA_ARGS__)
# define _ALIGNAS_TYPE(x) alignas(x)
# define _ALIGNAS(x) alignas(x)
# define _NOEXCEPT noexcept
@@ -348,7 +348,7 @@ _LIBCPP_HARDENING_MODE_DEBUG
# else
-# define _LIBCPP_ALIGNOF(_Tp) _Alignof(_Tp)
+# define _LIBCPP_ALIGNOF(...) _Alignof(__VA_ARGS__)
# define _ALIGNAS_TYPE(x) __attribute__((__aligned__(_LIBCPP_ALIGNOF(x))))
# define _ALIGNAS(x) __attribute__((__aligned__(x)))
# define nullptr __nullptr
diff --git a/libcxx/include/__type_traits/aligned_storage.h b/libcxx/include/__type_traits/aligned_storage.h
index 5c2208ae0c70a..33c0368d0c3c8 100644
--- a/libcxx/include/__type_traits/aligned_storage.h
+++ b/libcxx/include/__type_traits/aligned_storage.h
@@ -11,8 +11,6 @@
#include <__config>
#include <__cstddef/size_t.h>
-#include <__type_traits/integral_constant.h>
-#include <__type_traits/type_list.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -21,10 +19,10 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _Tp>
-struct __align_type {
- static const size_t value = _LIBCPP_PREFERRED_ALIGNOF(_Tp);
- typedef _Tp type;
-};
+struct _ALIGNAS(_LIBCPP_PREFERRED_ALIGNOF(_Tp)) _AlignedAsT {};
+
+template <class... _Args>
+struct __max_align_impl : _AlignedAsT<_Args>... {};
struct __struct_double {
long double __lx;
@@ -33,41 +31,16 @@ struct __struct_double4 {
double __lx[4];
};
-using __all_types _LIBCPP_NODEBUG =
- __type_list<__align_type<unsigned char>,
- __align_type<unsigned short>,
- __align_type<unsigned int>,
- __align_type<unsigned long>,
- __align_type<unsigned long long>,
- __align_type<double>,
- __align_type<long double>,
- __align_type<__struct_double>,
- __align_type<__struct_double4>,
- __align_type<int*> >;
-
-template <class _TL, size_t _Len>
-struct __find_max_align;
-
-template <class _Head, size_t _Len>
-struct __find_max_align<__type_list<_Head>, _Len> : public integral_constant<size_t, _Head::value> {};
-
-template <size_t _Len, size_t _A1, size_t _A2>
-struct __select_align {
-private:
- static const size_t __min = _A2 < _A1 ? _A2 : _A1;
- static const size_t __max = _A1 < _A2 ? _A2 : _A1;
-
-public:
- static const size_t value = _Len < __max ? __min : __max;
-};
+inline const size_t __aligned_storage_max_align =
+ _LIBCPP_ALIGNOF(__max_align_impl<unsigned long long, double, long double, __struct_double, __struct_double4, int*>);
-template <class _Head, class... _Tail, size_t _Len>
-struct __find_max_align<__type_list<_Head, _Tail...>, _Len>
- : public integral_constant<
- size_t,
- __select_align<_Len, _Head::value, __find_max_align<__type_list<_Tail...>, _Len>::value>::value> {};
+template <size_t _Len>
+inline const size_t __aligned_storage_alignment =
+ _Len > __aligned_storage_max_align
+ ? __aligned_storage_max_align
+ : size_t(1) << ((sizeof(size_t) * __CHAR_BIT__) - __builtin_clzg(_Len) - 1);
-template <size_t _Len, size_t _Align = __find_max_align<__all_types, _Len>::value>
+template <size_t _Len, size_t _Align = __aligned_storage_alignment<_Len> >
struct _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_NO_SPECIALIZATIONS aligned_storage {
union _ALIGNAS(_Align) type {
unsigned char __data[(_Len + _Align - 1) / _Align * _Align];
@@ -77,7 +50,7 @@ struct _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_NO_SPECIALIZATIONS aligned_storage {
#if _LIBCPP_STD_VER >= 14
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
-template <size_t _Len, size_t _Align = __find_max_align<__all_types, _Len>::value>
+template <size_t _Len, size_t _Align = __aligned_storage_alignment<_Len> >
using aligned_storage_t _LIBCPP_DEPRECATED_IN_CXX23 = typename aligned_storage<_Len, _Align>::type;
_LIBCPP_SUPPRESS_DEPRECATED_POP
|
| inline const size_t __aligned_storage_alignment = | ||
| _Len > __aligned_storage_max_align | ||
| ? __aligned_storage_max_align | ||
| : size_t(1) << ((sizeof(size_t) * __CHAR_BIT__) - __builtin_clzg(_Len) - 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC, this computes the largest power of two that is less than or equal to the given _Len. So for example, for sizeof(T) == 3, we get an alignment of 2. For sizeof(T) == 4, we get 4.
I don't understand how that's correct. I would have thought that sizeof(T) implies that the alignment of T >= 4, doesn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you convinced me that this was the right thing since the size of a struct is always a multiple of its alignment.
| inline const size_t __aligned_storage_alignment = | ||
| _Len > __aligned_storage_max_align | ||
| ? __aligned_storage_max_align | ||
| : size_t(1) << ((sizeof(size_t) * __CHAR_BIT__) - __builtin_clzg(_Len) - 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you convinced me that this was the right thing since the size of a struct is always a multiple of its alignment.
No description provided.